package com.sfy.mallchat.common.user.service.impl;

import cn.hutool.core.thread.NamedThreadFactory;
import cn.hutool.http.HttpUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.sfy.mallchat.common.user.dao.UserDao;
import com.sfy.mallchat.common.user.domain.entity.IpDetail;
import com.sfy.mallchat.common.user.domain.entity.IpInfo;
import com.sfy.mallchat.common.user.domain.entity.User;
import com.sfy.mallchat.common.user.service.IpService;
import com.sfy.mallchat.utils.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import com.sfy.mallchat.common.common.domain.ApiResult;

@Service
@Slf4j
public class IpServiceImpl implements IpService {

    private static ExecutorService executorService =
            new ThreadPoolExecutor(1, 1, 0L, TimeUnit.SECONDS,
                    new LinkedBlockingDeque<Runnable>(500),
                    new NamedThreadFactory("refresh-ipDetail", false));

    @Autowired
    private UserDao userDao;

    @Override
    public void refreshAsyncIpDetail(Long id) {
        executorService.execute(() -> {
            User user = userDao.getById(id);
            IpInfo ipInfo = user.getIpInfo();
            if (Objects.isNull(user)) {
                return;
            }
            String ip = ipInfo.needRefresh();
            if (StringUtils.isBlank(ip)) {
                return;
            }
            IpDetail ipDetail = tryGetIpDetailOrNullTreeTimes(ip);
            if (Objects.nonNull(ipDetail)) {
                ipInfo.refreshDetail(ipDetail);
                User update = new User();
                update.setId(id);
                update.setIpInfo(ipInfo);
                userDao.updateById(update);
            }
        });
    }


    private IpDetail tryGetIpDetailOrNullTreeTimes(String ip) {
        for (int i = 0; i < 3; i++) {
            IpDetail ipDetail = getIpDetailOrNull(ip);
            if (Objects.nonNull(ipDetail)) {
                return ipDetail;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                log.error("sleep error", e);
            }
        }
        return null;
    }

    private IpDetail getIpDetailOrNull(String ip) {
        String url = "https://ip.taobao.com/outGetIpInfo?ip=" + ip +
                "&accessKey=alibaba-inc";
        String data = HttpUtil.get(url);
        ApiResult<IpDetail> result = JsonUtils.toObj(data, new TypeReference<ApiResult>() {
        });
        IpDetail res = result.getData();
        if (Objects.isNull(res)) {
            return null;
        }
        return res;
    }
}
